#include "stdinc.h"
#include <CEGUI.h>
#include <Ogre.h>

#include "DwarfFort/InternalStructures.h"
#include "DwarfFort/Interface.h"

#include <stdio.h>
#include "Main/Logger.h"

#include "GUI/MapCellViewer.h"

using namespace GUI;



MapCellViewer::MapCellViewer(CEGUI::Window *parentSheet)
:mEditing(false),mUpdatingFlags(false)		
{
	mBlockRaep = false;
	mWindow = CEGUI::WindowManager::getSingleton().loadWindowLayout("MapCellView.layout");
	// mWindow->hide();
	parentSheet->addChildWindow(mWindow);

//	mValueList = (CEGUI::MultiColumnList*) CEGUI::WindowManager::getSingleton().getWindow("MapCellView/ValueList");
	
	//CEGUI::Checkbox * cb = (CEGUI::Checkbox*) CEGUI::WindowManager::getSingleton().getWindow("MapCellView/EnableView");
	//CEGUI::PushButton *pb =  (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("MapCellView/BlockRaep");

//	pb->subscribeEvent(CEGUI::PushButton::EventClicked,CEGUI::Event::Subscriber(&MapCellViewer::startRaep,this)); 
	

	memset(&mOldVals,0,sizeof(mOldVals));
	
	// quick hack for now :/
	mCursorX =(long *) 0x0094228C;
	mCursorY =(long *) 0x00942290;
	mCursorZ =(long *) 0x00942294;
//	populateValueList();

	/*CEGUI::Window *dw = CEGUI::WindowManager::getSingleton().getWindow("MapCellView/DesignationHolder");
	CEGUI::Window *fw = CEGUI::WindowManager::getSingleton().getWindow("MapCellView/FlagHolder");
	dw->setWidth(CEGUI::UDim(0,240));
	fw->setWidth(CEGUI::UDim(0,240));
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 8; j++)
		{
			int number = i*8+j;
			std::string numStr = Ogre::StringConverter::toString(number);
			std::string flagName = "Flag" + numStr;
			std::string desigName = "Desig" + numStr;
			CEGUI::UVector2 pos(CEGUI::UDim(0,j*30),CEGUI::UDim(0,i*15)) ;
			CEGUI::UDim width(0,j*30+30),height(0,i*15+15);

			CEGUI::Checkbox *flag =  (CEGUI::Checkbox *)CEGUI::WindowManager::getSingleton().createWindow("OgreDwarf/Checkbox",flagName.c_str());
			flag->setText(numStr.c_str());
			flag->setSelected(false);
			fw->addChildWindow(flag);
			flag->setPosition(pos);
			flag->setWidth(CEGUI::UDim(0,30));
			flag->setHeight(CEGUI::UDim(0,15));
			
			
			mFlags[number] = flag;
			flag->subscribeEvent(CEGUI::Checkbox::EventCheckStateChanged,CEGUI::Event::Subscriber(&MapCellViewer::flagChanged,this));

			CEGUI::Checkbox *desig =  (CEGUI::Checkbox *)CEGUI::WindowManager::getSingleton().createWindow("OgreDwarf/Checkbox",desigName.c_str());
			desig->setText(numStr.c_str());
			desig->setSelected(false);
			dw->addChildWindow(desig);
			desig->setPosition(pos);
			desig->setWidth(CEGUI::UDim(0,30));
			desig->setHeight(CEGUI::UDim(0,15));
			
			mOccupations[number] = desig;
			desig->subscribeEvent(CEGUI::Checkbox::EventCheckStateChanged,CEGUI::Event::Subscriber(&MapCellViewer::occupationChanged,this));
		}*/
}


MapCellViewer::~MapCellViewer()
{
  
}


void MapCellViewer::populateValueList()
{
	
	mValueList->addColumn("Name",0,CEGUI::UDim(0.5,0));
	mValueList->addColumn("Value",1,CEGUI::UDim(0.4,0));
	
	for (int i = 0; i <15 ; i++)
	{
		mNames[i]  = new CEGUI::ListboxTextItem(""); 
		mValueList->addRow(mNames[i],0,i);
		mValues[i] = new CEGUI::ListboxTextItem(""); 
		mValueList->setItem(mValues[i],1,i);
	}
	mValueList->enable();	
	mNames[0]->setText("Cursor x");
	mNames[1]->setText("Cursor y");
	mNames[2]->setText("Cursor z");
	mNames[3]->setText("Block type");
	mNames[4]->setText("Designations");
	mNames[5]->setText("Occupations");
	mNames[6]->setText("unknown 1");
	mNames[7]->setText("Pathfinding");
	mNames[8]->setText("unknown 2");
	mNames[9]->setText("unknown 3");
	mNames[10]->setText("unknown 4");
	mNames[11]->setText("temperature 1");
	mNames[12]->setText("temperature 2");
	mNames[13]->setText("unknown 4");
	mNames[14]->setText("unknown 4");

	
}


void MapCellViewer::update()
{
	if (mBlockRaep)
	{	
		blockRaep();
		return;
	}

	bool needs_update = false;
	if ((*mCursorX) < 0) 
	{
		if (mOldCursorX == *mCursorX) return;
		for (int i = 0; i <15 ; i++)
		{
			mValues[i]->setText("");
		}
		mOldCursorX = *mCursorX;
		mOldCursorY = *mCursorY;
		mOldCursorZ = *mCursorZ;
		mValueList->handleUpdatedItemData();
	//  mSelectionWidget->hide();
	  return;
	}
	long x = (*mCursorX) /16;
	long y = (*mCursorY) /16;
	long z = (*mCursorZ);
	long x1 = (*mCursorX) % 16;
	long y1 = (*mCursorY) % 16;
	long pos = x1 *16 + y1;

	//another hack for now :/
	DwarfFort::MapCell	*****cells = (DwarfFort::MapCell *****)0x014A60A4;
	DwarfFort::MapCell	*cell = (*cells)[x][y][z];
	if (!cell) return;

	if (mEditing || (
		mOldCursorX == *mCursorX &&
		mOldCursorY == *mCursorY &&
		mOldCursorZ == *mCursorZ &&
		mOldVals.blockType == cell->mBlocks[pos] &&
		mOldVals.MapDesignations == cell->mFlags1[pos] &&
		mOldVals.MapOccupations == cell->mFlags2[pos] &&
		mOldVals.unknown1 == cell->unknown1[pos] &&
		mOldVals.pathFinding == cell->pathFinding[pos] &&
		mOldVals.unknown2 == cell->unknown2[pos] &&
		mOldVals.unknown3 == cell->unknown3[pos] &&
		mOldVals.unknown4 == cell->unknown4[pos] &&
		mOldVals.temperature1 == cell->temperature1[pos] &&
		mOldVals.temperature2 == cell->temperature2[pos] &&
		mOldVals.unknown5 == cell->unknown5[pos] &&
		mOldVals.unknown6 == cell->unknown6[pos] )) return;
	mOldCursorX = *mCursorX;
	mOldCursorY = *mCursorY;
	mOldCursorZ = *mCursorZ;

	mOldVals.blockType = cell->mBlocks[pos];
	mOldVals.MapDesignations = cell->mFlags1[pos];
	mOldVals.MapOccupations = cell->mFlags2[pos];
	mOldVals.unknown1 = cell->unknown1[pos];
	mOldVals.pathFinding = cell->pathFinding[pos];
	mOldVals.unknown2 = cell->unknown2[pos];
	mOldVals.unknown3 = cell->unknown3[pos];
	mOldVals.unknown4 = cell->unknown4[pos];
	mOldVals.temperature1 = cell->temperature1[pos];
	mOldVals.temperature2 = cell->temperature2[pos];
	mOldVals.unknown5 = cell->unknown5[pos];
	mOldVals.unknown6 = cell->unknown6[pos];

	unsigned long flags = cell->mFlags1[pos]; 
	unsigned long occup = cell->mFlags2[pos];
	
	for (int i = 0 ;i <32 ;i++)
	{
		mFlags[i]->setMutedState(true); 
		mFlags[i]->setSelected((flags >> i) &1);
		mFlags[i]->setMutedState(false);
		mOccupations[i]->setMutedState(true);
		mOccupations[i]->setSelected((occup >> i) &1);
		mOccupations[i]->setMutedState(false);
	}
	


	mValues[0]->setText(Ogre::StringConverter::toString((*mCursorX)));
	mValues[1]->setText(Ogre::StringConverter::toString((*mCursorY)));
	mValues[2]->setText(Ogre::StringConverter::toString((*mCursorZ)));
	mValues[3]->setText("0x"+Ogre::StringConverter::toString(cell->mBlocks[pos],4,'0', std::ios::hex | std::ios::uppercase ));
	mValues[4]->setText("0x"+Ogre::StringConverter::toString(cell->mFlags1[pos],8,'0', std::ios::hex | std::ios::uppercase ));
	mValues[5]->setText("0x"+Ogre::StringConverter::toString(cell->mFlags2[pos],8,'0', std::ios::hex | std::ios::uppercase ));
	mValues[6]->setText("0x"+Ogre::StringConverter::toString(cell->unknown1[pos],2,'0', std::ios::hex | std::ios::uppercase ));
	mValues[7]->setText("0x"+Ogre::StringConverter::toString(cell->pathFinding[pos],8,'0', std::ios::hex | std::ios::uppercase ));
	mValues[8]->setText("0x"+Ogre::StringConverter::toString(cell->unknown2[pos],4,'0', std::ios::hex | std::ios::uppercase ));
	mValues[9]->setText("0x"+Ogre::StringConverter::toString(cell->unknown3[pos],4,'0', std::ios::hex | std::ios::uppercase ));
	mValues[10]->setText("0x"+Ogre::StringConverter::toString(cell->unknown4[pos],4,'0', std::ios::hex | std::ios::uppercase ));
	mValues[11]->setText("0x"+Ogre::StringConverter::toString(cell->temperature1[pos],4,'0', std::ios::hex | std::ios::uppercase ));
	mValues[12]->setText("0x"+Ogre::StringConverter::toString(cell->temperature2[pos],4,'0', std::ios::hex | std::ios::uppercase ));
	mValues[13]->setText("0x"+Ogre::StringConverter::toString(cell->unknown5[pos],4,'0', std::ios::hex | std::ios::uppercase ));
	mValues[14]->setText("0x"+Ogre::StringConverter::toString(cell->unknown6[pos],4,'0', std::ios::hex | std::ios::uppercase ));

	mValueList->handleUpdatedItemData(); 
}


bool MapCellViewer::valueChanged(const CEGUI::EventArgs &evt)

{
	_asm int 3;	

}




void MapCellViewer::blockRaep()
{
	if (mRaepBlock == 0x5FF)
	{
		mBlockRaep = false;
		return;
	}
		

	char buffer[91];
	memset(buffer,0,61);
	DwarfFort::MapCell	*****cells = (DwarfFort::MapCell *****)0x014A60A4;

	long x = (*mCursorX) /16;
	long y = (*mCursorY) /16;
	long z = (*mCursorZ);
	long x1 = (*mCursorX) % 16;
	long y1 = (*mCursorY) % 16;
	long pos = x1 *16 + y1;

	DwarfFort::MapCell	*cell = (*cells)[x][y][z];

	WORD *curX,*curY,*curZ;
	curX = (WORD*) (0xC40B40);
	curY = (WORD*) (0xC69378);
	curZ = (WORD*) (0xC69354);
	long _x = (*curX) /16;
	long _y = (*curY) /16;
	long _z = (*curZ);
	long _x1 = (*curX) % 16;
	long _y1 = (*curY) % 16;
	long pos2 = _x1 *16 + _y1;
	DwarfFort::MapCell	*cell2 = (*cells)[_x][_y][_z];

		
	DwarfFort::DwarfFortScreen *screen = DwarfFort::Interface::getSingleton().getScreen();

	long loc = 50*25+2;
	for (int i = 0; i < 30;i++)
	{
		DWORD val = screen->IconDataPointer[loc];
		val = val &0xff;
		buffer[i] = val;
		loc += 25;
	}
	 loc = 50*25+3;
	for (int i = 30; i < 630;i++)
	{
		DWORD val = screen->IconDataPointer[loc];
		val = val &0xff;
		buffer[i] = val;
		loc += 25;
	}
	

	buffer[60] = 0;
	loc = 25*1+1;
	DWORD val = screen->IconDataPointer[loc];
	BYTE val2 = val &0xff;

	mRaepBlock++;
	cell->mBlocks[pos] = mRaepBlock;
	cell2->mBlocks[pos2] = mRaepBlock;

	mFlagCounter++;
	
	if ((mFlagCounter & 0xFFFFFDFF) == mOldFlag) mFlagCounter+= 0x200;

	mOldFlag = mFlagCounter & 0xFFFFFDFF;
	cell->mFlags1[pos] = mOldFlag;
	cell2->mFlags2[pos] = mOldFlag;

	char buf2[2];
	buf2[0] = val2;
	buf2[1] = 0;
	std::string result = "0x" +Ogre::StringConverter::toString((int)mRaepBlock,4,'0',std::ios::hex | std::ios::uppercase) + " " + 
		                 buffer + " 0x" + 
						 Ogre::StringConverter::toString((int)val2,2,'0',std::ios::hex | std::ios::uppercase) +
						 " '"+buf2+"'";
	char buffer2[500];
	
	sprintf(buffer2,"0x%X    %s    0x%X    '%c'",mRaepBlock,buffer,val2,val2);


	FILE *f = fopen("cells.txt","a");
	
	fputs(buffer2,f);
	for (int i = 31; i >=0;i--)
		fprintf(f," %c ",((cell->mFlags1[pos] >> i) & 1)? '1':'0');
	fputs("\n",f);

	
	fclose(f);
};


bool MapCellViewer::startRaep(const CEGUI::EventArgs &evt)
{
	return true;
	mBlockRaep = true;

	DwarfFort::MapCell	*****cells = (DwarfFort::MapCell *****)0x014A60A4;

	long x = (*mCursorX) /16;
	long y = (*mCursorY) /16;
	long z = (*mCursorZ);
	long x1 = (*mCursorX) % 16;
	long y1 = (*mCursorY) % 16;
	long pos = x1 *16 + y1;

	DwarfFort::MapCell	*cell = (*cells)[x][y][z];

	WORD *curX,*curY,*curZ;
	curX = (WORD*) (0xC40B40);
	curY = (WORD*) (0xC69378);
	curZ = (WORD*) (0xC69354);
	long _x = (*curX) /16;
	long _y = (*curY) /16;
	long _z = (*curZ);
	long _x1 = (*curX) % 16;
	long _y1 = (*curY) % 16;
	long pos2 = _x1 *16 + _y1;
	DwarfFort::MapCell	*cell2 = (*cells)[_x][_y][_z];


	mRaepBlock = 1;
	cell->mBlocks[pos] = mRaepBlock;
	cell2->mBlocks[pos2] = mRaepBlock;

	mFlagCounter = 0;
	mOldFlag = 0;
	cell->mFlags1[pos] = mFlagCounter;
	cell2->mFlags1[pos] = mFlagCounter;

	return true;
}


bool MapCellViewer::flagChanged(const CEGUI::EventArgs &evt)
{
	
	const CEGUI::WindowEventArgs &evt2 = (const CEGUI::WindowEventArgs &)evt;
	CEGUI::Checkbox *cb = (CEGUI::Checkbox *) evt2.window; 
	if ((*mCursorX) < 0) 
	{
		cb->setSelected(false);
		return true;
	}
	std::string name = cb->getName().c_str();
	int number = Ogre::StringConverter::parseInt(cb->getText().c_str());
	unsigned long flag = (cb->isSelected() ? 1:0 ) << number;
	unsigned long mask = 1 << number;

	long x = (*mCursorX) /16;
	long y = (*mCursorY) /16;
	long z = (*mCursorZ);
	long x1 = (*mCursorX) % 16;
	long y1 = (*mCursorY) % 16;
	long pos = x1 *16 + y1;

	//another hack for now :/
	DwarfFort::MapCell	*****cells = (DwarfFort::MapCell *****)0x014A60A4;
	DwarfFort::MapCell	*cell = (*cells)[x][y][z];

	cell->mFlags1[pos] &=   0xFFFFFFFF - mask; // clear the original flag setting
	cell->mFlags1[pos] |=  flag; // add the new flag
	return true;
}

bool MapCellViewer::occupationChanged(const CEGUI::EventArgs &evt)
{
	const CEGUI::WindowEventArgs &evt2 = (const CEGUI::WindowEventArgs &)evt;
	CEGUI::Checkbox *cb = (CEGUI::Checkbox *) evt2.window; 
	if ((*mCursorX) < 0) 
	{
		cb->setSelected(false);
		return true;
	}
	std::string name = cb->getName().c_str();
	int number = Ogre::StringConverter::parseInt(cb->getText().c_str());
	unsigned long flag = (cb->isSelected() ? 1:0 ) << number;
	unsigned long mask = 1 << number;

	long x = (*mCursorX) /16;
	long y = (*mCursorY) /16;
	long z = (*mCursorZ);
	long x1 = (*mCursorX) % 16;
	long y1 = (*mCursorY) % 16;
	long pos = x1 *16 + y1;

	//another hack for now :/
	DwarfFort::MapCell	*****cells = (DwarfFort::MapCell *****)0x014A60A4;
	DwarfFort::MapCell	*cell = (*cells)[x][y][z];

	cell->mFlags2[pos] &=   0xFFFFFFFF - mask; // clear the original flag setting
	cell->mFlags2[pos] |=  flag; // add the new flag
	return true;
}